package com.bytz.modules.cms.statistic.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bytz.modules.cms.order.constant.OrderConstants;
import com.bytz.modules.cms.order.entity.Order;
import com.bytz.modules.cms.order.mapper.OrderMapper;
import com.bytz.modules.cms.order.model.OrderEndUserStatistic;
import com.bytz.modules.cms.order.model.ProductLineStatisticResult;
import com.bytz.modules.cms.order.service.IOrderItemService;
import com.bytz.modules.cms.reseller.util.ResellerSecurityUtils;
import com.bytz.modules.cms.statistic.enums.IntervalType;
import com.bytz.modules.cms.statistic.model.DateRangeModel;
import com.bytz.modules.cms.statistic.model.RecentOrderCount;
import com.bytz.modules.cms.statistic.model.TurnoverRequest;
import com.bytz.modules.cms.statistic.service.IStatisticService;
import com.bytz.modules.cms.statistic.util.DateRangeUtil;
import com.google.common.collect.TreeRangeMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class StatisticServiceImpl extends ServiceImpl<OrderMapper, Order> implements IStatisticService {

    @Autowired
    private IOrderItemService orderItemService;

    @Override
    public RecentOrderCount recentOrderCount() {

        String resellerId = ResellerSecurityUtils.getUserId();

        RecentOrderCount result = new RecentOrderCount();

        result.setWaitingEc(Math.toIntExact(lambdaQuery()
                .eq(Order::getResellerId, resellerId)
                .eq(Order::getEcRequired, OrderConstants.EcRequired.NECESSARY)
                .and(wrapper -> wrapper
                        .eq(Order::getEcStatus, OrderConstants.EcStatus.UNCOMMITTED).or()
                        .eq(Order::getEcStatus, OrderConstants.EcStatus.REJECT))
                .count()));

        result.setWaitingPickUp(Math.toIntExact(lambdaQuery()
                .eq(Order::getResellerId, resellerId)
                .eq(Order::getStatus, OrderConstants.OrderStatus.DAI_TI_JIAO_WEI_KUAN)
                .count()));

        result.setWaitingPrepay(Math.toIntExact(lambdaQuery()
                .eq(Order::getResellerId, resellerId)
                .eq(Order::getStatus, OrderConstants.OrderStatus.DAI_YU_FU)
                .count()));

        return result;
    }

    @Override
    public List<OrderEndUserStatistic> pieChart() {

        String resellerId = ResellerSecurityUtils.getUserId();

        List<OrderEndUserStatistic> orderEndUserStatistics = baseMapper.selectEndUserCount(resellerId, OrderConstants.OrderStatus.YI_WAN_CHENG);

        List<OrderEndUserStatistic> result = new ArrayList<>();
        Integer otherCount = 0;

        for (int i = 0; i < orderEndUserStatistics.size(); i++) {
            if (i >= 3) {
                otherCount += orderEndUserStatistics.get(i).getOrderCount();
            }
            if (i == orderEndUserStatistics.size() - 1) {
                OrderEndUserStatistic other = new OrderEndUserStatistic();
                other.setEndUserName("其他");
                other.setOrderCount(otherCount);
            }
            result.add(orderEndUserStatistics.get(i));
        }

        return result;
    }

    @Override
    public List<DateRangeModel> lineChart(TurnoverRequest turnoverRequest) {

        String resellerId = ResellerSecurityUtils.getUserId();

        IntervalType interval = turnoverRequest.getInterval();
        LocalDate start = DateRangeUtil.getStartDateByInterval(turnoverRequest.getStart().toLocalDate(), interval);
        LocalDate end = DateRangeUtil.getEndDateByInterval(turnoverRequest.getEnd().toLocalDate(), interval);

        TreeRangeMap<LocalDate, List<Order>> rangeMap = TreeRangeMap.create();

        DateRangeUtil.getRanges(start, end, interval).forEach(range -> {
            rangeMap.put(range, new ArrayList<>());
        });

        List<Order> orders = lambdaQuery()
                .select(Order::getCompleteTime, Order::getPaidPrice)
                .eq(Order::getResellerId, resellerId)
                .eq(Order::getStatus, OrderConstants.OrderStatus.YI_WAN_CHENG)
                .ge(Order::getCompleteTime, start)
                .lt(Order::getCompleteTime, end)
                .list();

        orders.forEach(order -> {
            List<Order> orderList = rangeMap.get(order.getCompleteTime().toLocalDate());
            if (orderList != null) {
                orderList.add(order);
            }
        });

        return rangeMap.asMapOfRanges().entrySet().stream().map(entry -> {
            DateRangeModel rangeModel = new DateRangeModel();
            rangeModel.setRange(entry.getKey());
            BigDecimal sum = entry.getValue().stream().map(Order::getPaidPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            rangeModel.setSum(sum);
            rangeModel.setCount(entry.getValue().size());
            return rangeModel;
        }).collect(Collectors.toList());
    }

    @Override
    public List<ProductLineStatisticResult> productLineTotal() {

        String resellerId = ResellerSecurityUtils.getUserId();

        return baseMapper.selectProductLineTotal(resellerId, OrderConstants.OrderStatus.YI_WAN_CHENG);
    }


}
